﻿

namespace Test
 module Path = 

    open System
    open System.Windows
    open System.Windows.Media
    open System.Windows.Shapes
    open System.Windows.Controls
    open FsSignals.Signal


    let makePath () = 
        let main = new DockPanel()
        let myPath = new Path();
        myPath.Stroke <- Brushes.Black;
        myPath.StrokeThickness <- 1.0;
        let mySolidColorBrush = Brushes.Black
        myPath.Fill <- mySolidColorBrush;
        main.Children.Add(myPath);
        main.Background <- Brushes.White
        (main, myPath)
  
    module Path1 = 
        let makePath() =
            let rec engine (ui:UIElement) = 
                
                let mldS = sourceEvent ui.MouseLeftButtonDown 
                
                let prt msg () =   printfn msg 
                let e (arg:Input.MouseButtonEventArgs) : Signal<Point list> = 
                            let mmdS = sourceEvent ui.MouseMove 
                            let s1 = scan  (fun path (arg:Input.MouseEventArgs)  -> arg.GetPosition(ui) :: path) [] mmdS 
                            let mrdS = sourceEvent ui.MouseRightButtonDown // |> map (fun _ -> ())
                            let s2 = sample s1 mrdS
                            let r = switch s2 (mrdS ==>> (fun _ -> engine ui))
                            r
                let s1 = wait (mldS =>> e)
                s1
    
            let (main, myPath) = makePath()
            let draw points = 
                let group = new GeometryGroup()
                let proc p1 p2 =    let line = new LineGeometry(p1, p2);
                                    group.Children.Add(line)
                                    p2
                List.reduce proc points
                myPath.Data <-  group
                 
            let s = engine main  =>> draw
            main

    module Path1Bis = 
        let makePath() =
            let rec engine (ui:UIElement) draw = 
                
                let mldS = sourceEvent ui.MouseLeftButtonDown 
                
                let prt msg () =   printfn msg 
                let e (arg:Input.MouseButtonEventArgs) = 
                            let mmdS = sourceEvent ui.MouseMove 
                            let s1 = scan  (fun path (arg:Input.MouseEventArgs)  -> arg.GetPosition(ui) :: path) [] mmdS 
                            let s1' = s1 =>> draw
                            let mrdS = sourceEvent ui.MouseRightButtonDown // |> map (fun _ -> ())
                            let s2 = sample s1 mrdS
                            switch s2 (mrdS ==>> (fun _ ->  dispose s1' 
                                                            engine ui draw))
                let s1 = wait (mldS =>> e)
                s1
    
            let (main, myPath) = makePath()
            let draw points = 
                let group = new GeometryGroup()
                let proc p1 p2 =    let line = new LineGeometry(p1, p2);
                                    group.Children.Add(line)
                                    p2
                List.reduce proc points
                myPath.Data <-  group
                 
            let s = engine main draw
            main

    module Path2 = 
    
        let makeWorkingPath() =
            let myPath = new Path();
            myPath.Stroke <- Brushes.Blue;
            myPath.StrokeThickness <- 1.0;
            let mySolidColorBrush = Brushes.Blue
            myPath.Fill <- mySolidColorBrush;
            myPath
    
        let makePath() =
        
            let (main, path) = makePath()
            let group = new GeometryGroup()
            path.Data <-  group
            
            let wgroup = new GeometryGroup()
            group.Children.Add(wgroup)
                
            let startPath p1 ((wgroup:GeometryGroup), (group:GeometryGroup), _) =
                ((wgroup:GeometryGroup), (group:GeometryGroup), p1)

            let drawPath p2 ((wgroup:GeometryGroup), (group:GeometryGroup), p1)  =
                let line = new LineGeometry(p1, p2);
                wgroup.Children.Add(line)
                ((wgroup:GeometryGroup), (group:GeometryGroup), p2)

            let cleanPath ((wgroup:GeometryGroup), (group:GeometryGroup), p1) =
                wgroup.Children.Clear()
                ((wgroup:GeometryGroup), (group:GeometryGroup), p1)

            let closePath ((wgroup:GeometryGroup), (group:GeometryGroup), p1) =
                group.Children.Add(wgroup.Clone())
                wgroup.Children.Clear()
                ((wgroup:GeometryGroup), (group:GeometryGroup), p1)
                
            let rec engine (ui:UIElement) = 
                
                let mldS = sourceEvent ui.MouseLeftButtonDown 
                
                let prt msg () =   printfn msg 
                let e () = 
                            let mmdS = sourceEvent ui.MouseMove 
                            let s1 = mmdS =>> (fun (arg:Input.MouseEventArgs) path ->   let pos = arg.GetPosition(ui)
                                                                                        drawPath pos path)
                            let mrdS = sourceEvent ui.MouseRightButtonDown 
                            let s2 = mrdS =>> (fun _ path ->    closePath path)
                            let s3 = mergeExc s2 s1

                            let mldS = sourceEvent ui.MouseLeftButtonDown 
                            let s4 = mldS =>> (fun _ path ->    cleanPath path)
                            let s5 = mergeExc s3 s4

                            switch s5 (mrdS ==>> (fun _ -> engine ui))
                let s1 = mldS =>> (fun (arg:Input.MouseButtonEventArgs) path -> startPath (arg.GetPosition(ui)) path)
                let s2 = switch s1 (mldS ==>> e)
               
                s2
                 
            let s = engine main 
            stepAccumSig (wgroup, group, new Point(0.0, 0.0)) s   
            main

        